package com.jesse.eclgy.plug.dao;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ReflectUtil;
import com.jesse.eclgy.plug.db.RecordSetPlus;
import com.jesse.eclgy.plug.util.ReflectionUtils;
import com.jesse.eclgy.plug.wrapper.*;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.util.*;

/*
 *基本DAO类型
 * @Author: jesse
 * @Date: 2023/6/3 16:13
 */

public class BaseDao<E> {
    @Getter
    private RecordSetPlus rsp = new RecordSetPlus();


    /**
     * 根据实体 写入数据库
     *
     * @param entity
     * @return
     * @throws Exception
     */
    public boolean save(E entity)
    {
        InsertWrapper wrapper = InsertWrapper.builder().inject(entity);
        return this.rsp.executeUpdate(wrapper);
    }

    /**
     * 批量更新包括新增和删除
     *
     * @param entityList
     * @return
     * @throws Exception
     */
    public boolean batchExecuteEntity(Collection<E> entityList)
    {
        List<IWrapper> listWrapper = new ArrayList<>();
        entityList.forEach(t -> listWrapper.add(InsertWrapper.builder().inject(t)));
        return this.rsp.executeBatchWrapper(listWrapper);
    }

    /**
     * 批量执行包装器
     *
     * @param wrapperList
     * @return
     */
    public boolean batchExecuteWrapper(Collection<IWrapper> wrapperList)
    {
        return this.rsp.executeBatchWrapper(wrapperList);
    }


    /**
     * 查詢全部數據
     *
     * @return
     */
    public <E> List<E> queryAll()
    {
        final QueryWrapper wrapper = createQueryWrapper();
        this.rsp.executeQuery(wrapper);
        return convertToEntity();
    }


    /**
     * 根据主键 查询
     *
     * @param id
     */
    public <E> E queryById(Object id)
    {
        final QueryWrapper wrapper = createQueryWrapper();
        wrapper.condition(ConditionWrapper.builder().eq(ReflectionUtils.getKeyNameByGenerics(this.getClass()), id));
        this.rsp.executeQuery(wrapper);
        final List<E> entityList = convertToEntity();
        return !entityList.isEmpty() ? entityList.get(0) : null;
    }

    /**
     * 查询根据包装器
     *
     * @param condition
     * @return
     */
    public <E> List<E> queryByWrapper(ConditionWrapper condition)
    {
        final QueryWrapper wrapper = createQueryWrapper();
        wrapper.condition(condition);
        this.rsp.executeQuery(wrapper);
        return convertToEntity();
    }


    /**
     * 根据MAP 查询
     *
     * @param map
     * @return
     */
    public <E> List<E> queryByMap(Map<String, Object> map)
    {
        final QueryWrapper wrapper = createQueryWrapper();
        wrapper.conditionMap(map);
        this.rsp.executeQuery(wrapper);

        return convertToEntity();
    }

    /**
     * 查询结果 转实体
     *
     * @param entity
     * @return
     */
    public <E> List<E> queryByEntity(E entity)
    {
        final QueryWrapper wrapper = createQueryWrapper();
        wrapper.condition(ConditionWrapper.builder().inject(entity));
        this.rsp.executeQuery(wrapper);
        return convertToEntity();
    }


    /**
     * 得到实体的查询包装器
     *
     * @return
     */
    private QueryWrapper createQueryWrapper()
    {
        QueryWrapper wrapper = QueryWrapper.builder();
        wrapper.tableName(ReflectionUtils.getTableName(this.getClass()));
        Class<?> entityClass = ReflectionUtils.getGenericsClass(this.getClass());
        wrapper.column(ReflectionUtils.getFields(entityClass).keySet());
        return wrapper;
    }


    /**
     * 结果集转实体
     *
     * @return
     */

    private <E> List<E> convertToEntity()
    {
        Class<?> entityClass = ReflectionUtils.getGenericsClass(this.getClass());
        final Map<String, Field> fields = ReflectionUtils.getFields(entityClass);

        List<E> result = new ArrayList<>();

        while (this.rsp.next())
        {
            Object entity = ReflectUtil.newInstance(entityClass);

            fields.forEach((dbName, field) -> {
                if (field.getType() == Integer.class)
                {
                    ReflectUtil.setFieldValue(entity, field, this.rsp.getInt(dbName));
                } else if (field.getType() == Double.class)
                {
                    ReflectUtil.setFieldValue(entity, field, this.rsp.getDouble(dbName));
                } else if (field.getType() == Long.class)
                {
                    ReflectUtil.setFieldValue(entity, field, Convert.toLong(this.rsp.getString(dbName), 0L));
                } else if (field.getType() == java.util.Date.class)
                {
                    if (StringUtils.isNotBlank(this.rsp.getString(dbName)))
                    {
                        DateTime parse = DateUtil.parse(this.rsp.getString(dbName));
                        ReflectUtil.setFieldValue(entity, field, parse);
                    }
                } else
                {
                    ReflectUtil.setFieldValue(entity, field, this.rsp.getString(dbName));
                }

            });
            result.add((E) entity);
        }
        return result;
    }

    /**
     * 结果集转MAP 行号 和 数据
     *
     * @return
     */
    public Map<Integer, Map<String, String>> convertToMap()
    {
        Map<Integer, Map<String, String>> result = new HashMap<>();
        int rowIndex = 0;
        while (this.rsp.next())
        {
            Map<String, String> rowData = new LinkedHashMap<>();

            for (String col : this.rsp.getColumnName())
            {
                rowData.put(col, this.rsp.getString(col));
            }
            result.put(rowIndex, rowData);
            rowIndex++;
        }
        return result;
    }

    /**
     * 根据实体更新数据 根据主键来更新
     *
     * @param entity
     * @return
     */
    public boolean update(E entity)
    {
        final UpdateWrapper wrapper = UpdateWrapper.builder().inject(entity);
        return this.executeWrapper(wrapper);
    }

    /**
     * 根据包装器更新
     *
     * @param wrapper
     * @return
     */
    public boolean updateByWrapper(UpdateWrapper wrapper)
    {
        wrapper.tableName(ReflectionUtils.getTableName(this.getClass()));
        return this.executeWrapper(wrapper);
    }


    /**
     * 根据主键更新
     *
     * @param updateFieldMap
     * @return
     */
    public boolean updateMap(Map<String, Object> updateFieldMap, Map<String, Object> conditionMap)
    {
        final UpdateWrapper wrapper = UpdateWrapper.builder();
        wrapper.tableName(ReflectionUtils.getTableName(this.getClass()));
        wrapper.set(updateFieldMap);
        wrapper.condition(conditionMap);
        return this.executeWrapper(wrapper);
    }

    /**
     * 根据Map更新
     *
     * @param entity
     * @return
     */
    public boolean updateByMap(E entity, Map<String, Object> conditionMap)
    {
        final UpdateWrapper wrapper = UpdateWrapper.builder().inject(entity);
        wrapper.condition(ConditionWrapper.builder().condition(conditionMap));
        return this.executeWrapper(wrapper);
    }

    /**
     * 更新字段 根据 条件包装器
     *
     * @param entity
     * @param condition
     * @return
     */
    public boolean updateByMap(E entity, ConditionWrapper condition)
    {
        final UpdateWrapper wrapper = UpdateWrapper.builder().inject(entity);
        wrapper.condition(condition);
        return this.executeWrapper(wrapper);
    }

    /**
     * 根据实体内容删除
     *
     * @param entity
     * @return
     */
    public boolean delete(E entity)
    {
        final DeleteWrapper wrapper = DeleteWrapper.builder().inject(entity);
        wrapper.condition(ConditionWrapper.builder().inject(entity));
        return this.executeWrapper(wrapper);
    }

    /**
     * 根据主键 删除
     *
     * @param id
     * @return
     */
    public boolean deleteById(Object id)
    {
        final DeleteWrapper wrapper = DeleteWrapper.builder();
        wrapper.tableName(ReflectionUtils.getTableName(this.getClass()));
        wrapper.condition(ConditionWrapper.builder().eq(ReflectionUtils.getKeyNameByGenerics(this.getClass()), id));
        return this.executeWrapper(wrapper);
    }

    /**
     * 删除操作根据列
     *
     * @param field
     * @param value
     * @return
     */
    public boolean deleteByField(String field, Object value)
    {
        final DeleteWrapper wrapper = DeleteWrapper.builder();
        wrapper.tableName(ReflectionUtils.getTableName(this.getClass()));
        wrapper.conditionEQ(field, value);
        return this.executeWrapper(wrapper);
    }

    /**
     * 删除 根据map
     *
     * @param map
     * @return
     */
    public boolean deleteByMap(Map<String, Object> map)
    {
        final DeleteWrapper wrapper = DeleteWrapper.builder();
        wrapper.tableName(ReflectionUtils.getTableName(this.getClass()));
        wrapper.condition(map);
        return this.executeWrapper(wrapper);
    }

    /**
     * 删除操作 根据 包装器
     *
     * @param condition
     * @return
     */
    public boolean deleteByWrapper(ConditionWrapper condition)
    {
        final DeleteWrapper wrapper = DeleteWrapper.builder();
        wrapper.tableName(ReflectionUtils.getTableName(this.getClass()));
        wrapper.condition(condition);
        return this.executeWrapper(wrapper);
    }


    /**
     * 更新执行 包装器
     *
     * @param wrapper
     * @return
     */

    public Boolean executeWrapper(IWrapper wrapper)
    {
        return this.rsp.executeUpdate(wrapper);
    }


    /**
     * 得到泛型类型
     *
     * @return
     */
    public Class<?> getElementType()
    {
        return ReflectionUtils.getGenericsClass(this.getClass());
    }


}
